﻿using ECBS_Backend.dao;
using ECBS_Backend.model;
using System.Linq;
using System;
using System.Data;
using System.Collections;
using System.IO;
using System.Text;
using iTextSharp.text.pdf;
using iTextSharp.text;
using System.Collections.Generic;
using ECBS_Backend.utils;
using Microsoft.AspNetCore.Http;
using iTextSharp.text.pdf.parser;

namespace ECBS_Backend.service
{
    public class EnrollmentService
    {
        private readonly ECBSContext context;

        private HttpUtils httpUtils;

        public EnrollmentService(ECBSContext context, HttpUtils httpUtils)
        {
            this.context = context;
            this.httpUtils = httpUtils;
        }


        /// <summary>
        /// 验证学籍是否存在
        /// </summary>
        /// <param name="studentNumber"></param>
        /// <returns></returns>
        public bool EnrollmentExist(string studentNumber, string schoolName){
            var enrollmentClaim = context.EnrollmentClaims.SingleOrDefault(e => e.StudentNumber == studentNumber && e.SchoolName == schoolName);
            if(enrollmentClaim == null){
                return false;
            }else{
                return true;
            }
        }

        /// <summary>
        /// 上传学籍
        /// </summary>
        /// <param name="enrollment"></param>
        /// <param name="schoolWeID"></param>
        /// <returns></returns>
        public EnrollmentClaim IssueEnrollment(EnrollmentClaim enrollment, string schoolWeID)
        {
            enrollment.EnrollmentClaimId = Guid.NewGuid().ToString("N");
            School school = context.Schools.SingleOrDefault(s => s.WeID == schoolWeID);
            enrollment.SchoolName = school.Name;

            // 学籍证书上链
            string resp = httpUtils.createEnrollmentCredential(schoolWeID, enrollment);
            EnrollmentCredential enrollmentCredential = new EnrollmentCredential();
            enrollmentCredential.StudentNumber = enrollment.StudentNumber;
            enrollmentCredential.EnrollmentCredentialContext = resp;

            // claim信息存入数据库
            var e1 = context.EnrollmentClaims.SingleOrDefault(e => e.StudentNumber == enrollment.StudentNumber);
            if(e1 != null){
                throw new Exception("该学生的学号已经存在与学籍库中！");
            }

            var e2 = context.EnrollmentClaims.SingleOrDefault(e => e.IdentityCardId == enrollment.IdentityCardId);
            if(e2 != null){
                throw new Exception("该学生的身份证号已经存在于学籍库中！");
            }

            context.EnrollmentClaims.Add(enrollment);

            // 上链返回credential信息存入数据库
            context.EnrollmentCredentials.Add(enrollmentCredential);

            if (context.SaveChanges() <= 1)
            {
                throw new Exception("添加失败");
            }

            return enrollment;
        }

        /// <summary>
        /// 从数据库中删除学籍证书
        /// </summary>
        public EnrollmentClaim DeleteEnrollment(string studentNumber, string schoolWeId)
        {
            // 删除学生账号
            var student = context.Students.SingleOrDefault(s => s.StudentNumber == studentNumber && s.SchoolWeId == schoolWeId);
            if (student == null)
            {
                throw new Exception("未找到该学生账号");
            }

            context.Students.Remove(student);
            context.SaveChanges();

            // 删除claim信息
            var enrollmentClaim = context.EnrollmentClaims.SingleOrDefault(e => e.StudentNumber == studentNumber);
            if(enrollmentClaim == null){
                return null;
            }

            context.EnrollmentClaims.Remove(enrollmentClaim);
            context.SaveChanges();

            // 删除创建credential返回的信息
            var enrollmentCredential = context.EnrollmentCredentials.SingleOrDefault(e => e.StudentNumber == studentNumber);
            if (enrollmentCredential == null)
            {
                return null;
            }

            context.EnrollmentCredentials.Remove(enrollmentCredential);

            var gradeClaim = context.GradeClaims.SingleOrDefault(s => s.StudentNumber == studentNumber);
            if(gradeClaim == null)
            {
                return null;
            }

            context.GradeClaims.Remove(gradeClaim);
            context.SaveChanges();

            var gradeCredential = context.GradeCredentials.SingleOrDefault(s => s.StudentNumber == studentNumber);
            if(gradeCredential == null)
            {
                return null;
            }

            context.GradeCredentials.Remove(gradeCredential);
            context.SaveChanges();

            return enrollmentClaim;
        }

        /// <summary>
        /// 从数据库中获得学籍信息
        /// </summary>
        public EnrollmentClaim GetEnrollment(string schoolName, string studentNumber)
        {
            EnrollmentClaim enrollment = context.EnrollmentClaims.SingleOrDefault(e => e.SchoolName == schoolName && e.StudentNumber == studentNumber);
            if(enrollment == null)
            {
                throw new Exception("学籍不存在！");
            }
            return enrollment;

        }

        /// <summary>
        /// 下载学籍信息
        /// </summary>
        public byte[] DownloadEnrollment(string schoolName, string studentNumber)
        {
            EnrollmentClaim e = context.EnrollmentClaims.SingleOrDefault(e => e.StudentNumber == studentNumber && e.SchoolName == schoolName);

            if (e == null)
            {
                throw new Exception("没有您的学籍信息，无法下载！");
            }

            DataTable dt = new DataTable();
            dt.Columns.Add("key", typeof(string));
            dt.Columns.Add("value", typeof(string));

            List<string[]> lists = new List<string[]>();
            string[] value1 = { "学籍证书编号", e.EnrollmentClaimId };
            string[] value2 = { "学号", e.StudentNumber };
            string[] value3 = { "颁发时间", new DateTime((Convert.ToInt64(e.EnrollTime) * 10000) + 621355968000000000).ToString() };
            string[] value4 = { "专业名称", e.CollegeName };
            string[] value5 = { "出生年月", new DateTime((Convert.ToInt64(e.Birthday) * 10000) + 621355968000000000).ToString()};

            string temp = "男";
            if(e.Sex == "female"){
                temp = "女";
            }

            string[] value6 = { "性别", temp};
            string[] value7 = { "身份证号", e.IdentityCardId};
            string[] value8 = { "学校名称", e.SchoolName };

            lists.Add(value1);
            lists.Add(value2);
            lists.Add(value3);
            lists.Add(value4);
            lists.Add(value5);
            lists.Add(value6);
            lists.Add(value7);
            lists.Add(value8);


            foreach (string[] s in lists)
            {
                DataRow row = dt.NewRow();
                row["key"] = s[0];
                row["value"] = s[1];
                dt.Rows.Add(row);
            }


            string path = (System.Environment.CurrentDirectory) + "/src/学籍模板.pdf";
            ConvertDataTableToPDF(dt, path, 16);


            using (FileStream fs = new FileStream(path, FileMode.Open))
            {
                byte[] bytes = new byte[(int)fs.Length];
                fs.Read(bytes, 0, bytes.Length);
                fs.Close();

                if (File.Exists(path))
                {
                    File.Delete(path);
                }

                return bytes;
            }
        }

        /// <summary>
        /// 转化pdf格式函数
        /// </summary>
        /// <param name="Data"></param>
        /// <param name="PDFFile"></param>
        /// <param name="FontSize"></param>
        /// <returns></returns>
        public bool ConvertDataTableToPDF(DataTable Data, string PDFFile, float FontSize)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

            Document document = new Document();
            PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(PDFFile, FileMode.Create));
            document.Open();

            string path = System.Environment.CurrentDirectory + @"/src/simkai.ttf";
            BaseFont bf = BaseFont.CreateFont(path, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            iTextSharp.text.Font fontChinese = new iTextSharp.text.Font(bf, 12, iTextSharp.text.Font.NORMAL, new BaseColor(0, 0, 0));

            Font font = new Font(bf, FontSize);
            PdfPTable table = new PdfPTable(Data.Columns.Count);

            // Font font = new Font();

            table.WidthPercentage = 100;
            table.DefaultCell.Padding = 1;
            table.DefaultCell.BorderWidth = 1;
            table.DefaultCell.HorizontalAlignment = Element.ALIGN_LEFT;

            

            for (int i = 0; i < Data.Rows.Count; i++)
            {
                for (int j = 0; j < Data.Columns.Count; j++)
                {
                    table.AddCell(new Phrase(Data.Rows[i][j].ToString(), font));
                }
            }
            document.Add(table);
            document.Close();
            writer.Close();
            return true;
        }

        /// <summary>
        /// 验证学籍信息
        /// </summary>
        /// <returns></returns>
        public bool VertifyEnrollment(IFormFile file)
        {
            // 需要验证的claim
            EnrollmentClaim enrollmentClaim = ConvertPDFToDataTable(file);

            // 从数据库中获得credential的context
            EnrollmentCredential enrollmentCredential = context.EnrollmentCredentials.SingleOrDefault(e => e.StudentNumber == enrollmentClaim.StudentNumber);
            if (enrollmentCredential == null)
            {
                throw new Exception("该学生学籍不存在！");
            }
            string credentialContext = enrollmentCredential.EnrollmentCredentialContext;
            

            // 调用rest api函数验证
            return httpUtils.verifyEnrollment(enrollmentClaim, credentialContext);
        }

        /// <summary>
        /// pdf转化为EnrollmentClaim对象
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public EnrollmentClaim ConvertPDFToDataTable(IFormFile file)
        {
            // 验证是否是pdf文件
            var ext = System.IO.Path.GetExtension(file.FileName).ToLower();
            if (ext != ".pdf")
            {
                throw new Exception("只能上传pdf文件!");
            }

            try
            {
                // 返回的EnrollmentClaim对象
                EnrollmentClaim enrollmentClaim = new EnrollmentClaim();

                // 生成临时文件
                var path = (Environment.CurrentDirectory) + "/src/验证学籍临时文件.pdf";
                using (var stream = new FileStream(path, FileMode.Create))
                {
                    file.CopyTo(stream);
                    stream.Close();
                }


                // 读取pdf内容
                var pdfReader = new PdfReader(path);

                ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
                string value = PdfTextExtractor.GetTextFromPage(pdfReader, 1, strategy);
                // "学籍账号 2\n学号 2019\n颁发时间 1970/1/3 15:53:20\n学校名称 武汉大学\n出生年月 1970/1/1 0:21:40\n性别 女\n身份证号 32165498710"
                string[] dataInfo = value.Replace("\n", "@").Split('@');

                // 学籍账号
                int idxStart = dataInfo[0].IndexOf(" ") + 1;
                dataInfo[0] = dataInfo[0].Substring(idxStart, dataInfo[0].Length - idxStart);
                enrollmentClaim.EnrollmentClaimId = dataInfo[0];

                // 学号
                idxStart = dataInfo[1].IndexOf(" ") + 1;
                dataInfo[1] = dataInfo[1].Substring(idxStart, dataInfo[1].Length - idxStart);
                enrollmentClaim.StudentNumber = dataInfo[1];

                // 颁发时间
                idxStart = dataInfo[2].IndexOf(" ") + 1;
                dataInfo[2] = dataInfo[2].Substring(idxStart, dataInfo[2].Length - idxStart);
                DateTime dateTime = Convert.ToDateTime(dataInfo[2]);
                DateTime startTime = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1, 0, 0, 0, 0), TimeZoneInfo.Local);
                long t = (dateTime.Ticks - startTime.Ticks) / 10000;
                enrollmentClaim.EnrollTime = t;

                // 专业名称
                idxStart = dataInfo[3].IndexOf(" ") + 1;
                dataInfo[3] = dataInfo[3].Substring(idxStart, dataInfo[3].Length - idxStart);
                enrollmentClaim.CollegeName = dataInfo[3];

                // 出生年月
                idxStart = dataInfo[4].IndexOf(" ") + 1;
                dataInfo[4] = dataInfo[4].Substring(idxStart, dataInfo[4].Length - idxStart);
                dateTime = Convert.ToDateTime(dataInfo[4]);
                t = (dateTime.Ticks - startTime.Ticks) / 10000;
                enrollmentClaim.Birthday = t;

                // 性别
                idxStart = dataInfo[5].IndexOf(" ") + 1;
                dataInfo[5] = dataInfo[5].Substring(idxStart, dataInfo[5].Length - idxStart);
                if(dataInfo[5] == "女"){
                    enrollmentClaim.Sex = "female";
                }else{
                    enrollmentClaim.Sex = "male";
                }
                

                // 身份证号
                idxStart = dataInfo[6].IndexOf(" ") + 1;
                dataInfo[6] = dataInfo[6].Substring(idxStart, dataInfo[6].Length - idxStart);
                enrollmentClaim.IdentityCardId = dataInfo[6];

                // 学校名称
                idxStart = dataInfo[7].IndexOf(" ") + 1;
                dataInfo[7] = dataInfo[7].Substring(idxStart, dataInfo[7].Length - idxStart);
                enrollmentClaim.SchoolName = dataInfo[7];

                pdfReader.Close();

                if (File.Exists(path))
                {
                    File.Delete(path);
                }


                return enrollmentClaim;
            }
            catch(Exception)
            {
                throw new Exception("您上传的pdf格式有误！");
            }
        }
    }
}
